#include <linux/module.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
//添加输入子系统的头文件
#include <linux/input.h>

#define DEBOUNCE_DELAY 20  // 消抖延迟（毫秒）
#define DEVICE_NAME "key_driver"

static int irq_num;
static struct timer_list debounce_timer;
static int button_state = 0;  // 保存按键状态
static int button_gpio;
//定义一个输入设备test_dev
struct input_dev *test_dev; //定义一个输入设备test_dev

// 定时器回调函数
static void debounce_timer_callback(unsigned long data)
{
    int value = gpio_get_value(button_gpio); // 读取 GPIO 的当前值

    if (value != button_state) {
        button_state = value;
        pr_info("Button state changed: %d\n", button_state);
    }

    pr_info("input_report_key value: %d\n", value);
    input_report_key(test_dev, KEY_1, value); //上报事件
	input_sync(test_dev);
}

// 中断处理函数
static irqreturn_t button_irq_handler(int irq, void *dev_id)
{
    // 停止当前定时器并重新设置时间
    mod_timer(&debounce_timer, jiffies + msecs_to_jiffies(DEBOUNCE_DELAY));
    pr_info("button_irq_handler!\n");
    return IRQ_HANDLED;
}

static int __init button_driver_init(void)
{
    int ret;
    struct device_node *node;

    // 获取设备树节点
    node = of_find_compatible_node(NULL, NULL, "key0-test");
    if (!node) {
        pr_err("Failed to find device tree node\n");
        return -ENODEV;
    }

    // 从设备树中获取 GPIO
    button_gpio = of_get_named_gpio(node, "key1-gpio", 0);
    if (button_gpio < 0) {
        pr_err("Failed to get GPIO from device tree\n");
        return button_gpio;
    }

    // 申请 GPIO
    ret = gpio_request(button_gpio, "button_gpio");
    if (ret) {
        pr_err("Failed to request GPIO %d\n", button_gpio);
        return ret;
    }

    // 设置 GPIO 为输入模式
    ret = gpio_direction_input(button_gpio);
    if (ret) {
        pr_err("Failed to set GPIO %d as input\n", button_gpio);
        goto fail_free_gpio;
    }

    // 获取 GPIO 的中断号
    irq_num = gpio_to_irq(button_gpio);
    if (irq_num < 0) {
        pr_err("Failed to get IRQ number for GPIO %d\n", button_gpio);
        ret = irq_num;
        goto fail_free_gpio;
    }

    // 注册中断处理程序
    ret = request_irq(irq_num, button_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_driver", NULL);
    if (ret) {
        pr_err("Failed to request IRQ %d\n", irq_num);
        goto fail_free_gpio;
    }

    // 初始化定时器
    setup_timer(&debounce_timer, debounce_timer_callback, 0);

    //申请一个 input_dev输入设备
	test_dev = input_allocate_device();
	// 设置 input_dev 名字
	test_dev->name = "test_key";
	// 设置事件和事件值
	// 设置产生按键事件
	__set_bit(EV_KEY, test_dev->evbit);
	//设置产生哪些按键值，表示这个设备要支持key_1
	__set_bit(KEY_1, test_dev->keybit);
	//向 Linux内核注册 input_dev
	ret = input_register_device(test_dev);
    if (ret < 0)
	{
		printk("input_register_device is error \n");
		goto error_input_register;
	}

    pr_info("Button driver initialized\n");
    return 0;


error_input_register:
	input_unregister_device(test_dev);
fail_free_gpio:
    gpio_free(button_gpio);
    return ret;
}

static void __exit button_driver_exit(void)
{
    del_timer_sync(&debounce_timer);  // 删除定时器
    free_irq(irq_num, NULL);          // 释放中断
    gpio_free(button_gpio);           // 释放 GPIO
    input_unregister_device(test_dev); // 注销输入子系统
    pr_info("Button driver exited\n");
}

module_init(button_driver_init);
module_exit(button_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Button driver with debounce using timer from device tree");